#coding=utf-8
import os, random, logging
from datetime import datetime as dt
from sqlalchemy import Column, Integer, Unicode
from sqlalchemy.orm import synonym
from ext.model import DBSession
from util.file_util import create_zip

log = logging.getLogger(__name__)

class FileModelMixin():

    __seperator__ = '/'
    __tablename__ = 'com_file'
    __downloaddir__ = '/download'
    __downloadurl__ = '/download'

    __tablename__ = 'com_file'
    _publicdir = ''
    _downloaddir = os.path.abspath('')+'/reportlayout/public/upload'.replace('/', os.sep)
    _downloadurl = '/upload'

    file_name = Column(Unicode(255))
    file_path = Column(Unicode(1000), nullable=False)

    @classmethod
    def get(cls, id):
        return DBSession.query(cls).get(id)

    @classmethod
    def create(cls, **kw):
        obj = cls(**kw)
        DBSession.add(obj)
        DBSession.flush()
        return obj

    @classmethod
    def upload(cls, attachment_list, attachment_name_list=None, folder="sys", return_obj=False):
        #if not (attachment_list and attachment_name_list) : return (1,[])
        if type(attachment_list) != list : attachment_list = [attachment_list]
        if not attachment_name_list: attachment_name_list = [getattr(i,'filename',None) for i in attachment_list]
        if type(attachment_name_list) != list : attachment_name_list = [attachment_name_list]
        if len(attachment_list) != len(attachment_name_list) : return (2, [])

        def _todo(a, n):
            try:
                file_path = a.filename
                (pre, ext) = os.path.splitext(file_path)

                path_prefix = os.path.join(__downloaddir__, folder)
                if not os.path.exists(path_prefix) : os.makedirs(path_prefix)

                file_name = "%s%.4d%s" % (dt.now().strftime("%Y%m%d%H%M%S"), random.randint(1, 1000), ext)
                full_path = os.path.join(path_prefix, file_name)

                f = open(full_path, "wb")
                f.write(a.file.read())
                f.close()

                db_file_name = n or file_name
                if db_file_name.find(".") < 0 : db_file_name = db_file_name + ext

                obj = cls.create(**dict(file_name=db_file_name, file_path=os.path.join(folder, file_name)))
                return obj.id if not return_obj else obj
            except:
                logError()
                return None

        return (0, [_todo(a, n) for a, n in zip(attachment_list, attachment_name_list) if hasattr(a, "filename")])

    @property
    def resize_img(self):
        pass

    @property
    def rel_url(self):
        url = '%s/%s' % (self._downloadurl, self.file_path.replace('\\', '/'))
        return url.replace('//', '/')

    @property
    def abs_url(self):
        url = '%s%s/%s' % (config.website_url, self._downloadurl, self.file_path.replace('\\', '/'))
        return url.replace('//', '/')

    @property
    def pwd(self):
        return os.path.join(self._downloaddir, self.file_path)

class FileMixin():

    __filemodel__ = None
    __downloaddir__ = __filemodel__.__downloaddir__

    def get_files(self, key='attachment', wrapper=True, seperator='|'):
        try:
            if not wrapper: return [id for id in getattr(self, key).split(seperator) if id]
            m = lambda id: __filemodel__.get(id)
            return map(m, [id for id in getattr(self, key).split(seperator) if id])
        except:
            return []

    def get_file_pathes(self, key='attachment', wrapper=True, seperator='|'):
        return [i.pwd for i in self.get_files(key, wrapper, seperator)]

    @classmethod
    def upload_files(cls, *keys, **kw):
        try:
            if not keys:
                keys = ('attachment')
            for key in keys:
                if kw.has_key(key):
                    (flag, ids) = __filemodel__.upload(kw[key])
                    if flag != 0: 
                        raise "Error when upload the file(s)"
                    else:
                        kw[key] = ids
            return kw
        except Exception, e:
            transaction.doom()
            log.exception(str(e))
            raise

    def add_files(self, attachments=[], key='attachment', seperator='|'):
        try:
            ids = []
            for att in attachments:
                upObj = __filemodel__.create(**{'file_path':att, 'file_name': att.split('\\')[-1].split('/')[-1]})
                ids.append(upObj.id)
            setattr(self, key, seperator.join(map(str, ids)))
        except Exception, e:
            transaction.doom()
            log.exception(str(e))
            raise

    def download_file(self, key='attachment', wrapper=True):
        attachments = []
        zname = None
        for i in self.get_files(key, wrapper):
            attachments.append([i.pwd, i.file_name])
            if not zname:
                zname = i.file_name.split('.')[0]
        zfolder = os.path.join(__downloaddir__, 'temp')
        if not os.path.exists(zfolder):
            os.makedirs(zfolder)
        zfile = os.path.join(zfolder, '%s.zip' % zname)
        create_zip(zfile, attachments)
        return zfile

    @classmethod
    def download_files(cls, ids, key='attachment', name='dl', wrapper=True):
        orders = cls.find_by_ids(ids)
        attachments = []
        for i in orders:
            for j in i.get_files(key, wrapper):
                attachments.append([j.pwd, j.file_name])
        zfolder = os.path.join(__downloaddir__, 'temp')
        if not os.path.exists(zfolder):
            os.makedirs(zfolder)
        zfile = os.path.join(zfolder, '%s-%s.zip' % (name, dt.now().strftime("%Y%m%d%H%M%S")))
        create_zip(zfile, attachments)
        return zfile

